<?php

namespace pmvc\ioc\xml;

use DOMDocument;
use DOMXPath;
use Exception;
use ReflectionClass;

/**
 * A parse context.
 */
class ParseContext {

	private $doc;
	private $xpath;
	private $extensions;
	private $xmlFile;
	private $objectFactory;

	/**
	 * Creates the parse context.
	 * @param DOMDocument $doc
	 * @param DOMXPath $xpath
	 * @param string $xmlFile
	 * @param XmlObjectFactory $objectFactory
	 */
	public function __construct(
		DOMDocument $doc, DOMXPath $xpath, $xmlFile, XmlObjectFactory $objectFactory) {
		$this->doc				= $doc;
		$this->xpath			= $xpath;
		$this->xmlFile			= $xmlFile;
		$this->objectFactory	= $objectFactory;
	}

	/**
	 * Returns the document.
	 * @return DOMDocument
	 */
	public function getDocument() {
		return $this->doc;
	}

	/**
	 * Returns the document.
	 * @return DOMXPath
	 */
	public function getXPath() {
		return $this->xpath;
	}

	/**
	 * Returns the XML file.
	 * @return string
	 */
	public function getXmlFile() {
		return $this->xmlFile;
	}

	/**
	 * Returns the {@link XmlObjectFactory}.
	 * @return XmlObjectFactory
	 */
	public function getObjectFactory() {
		return $this->objectFactory;
	}

	/**
	 * Registers an extension.
	 * @param string $ns
	 * @param string $elementName
	 * @param string $extensionClass
	 */
	public function registerExtension($ns, $elementName, $extensionClass) {
		$this->extensions[$ns][$elementName] = Array(null, $extensionClass);
	}

	/**
	 * Returns the {@link Extension} registered for the
	 * given namespace and element name.
	 * @param string $ns
	 * @param string $elementName
	 * @return Extension
	 * @throws Exception on error
	 */
	public function getExtension($ns, $elementName) {

		// make sure it exists
		if (!isset($this->extensions[$ns])
			|| !isset($this->extensions[$ns][$elementName])) {
			throw new Exception(
				"extension for namespace ".$ns." and element ".$elementName." not found");
		}

		// look for existing extension
		if (isset($this->extensions[$ns][$elementName][0])) {
			return $this->extensions[$ns][$elementName][0];
		}

		// laod it
		$clazz = new ReflectionClass($this->extensions[$ns][$elementName][1]);
		$this->extensions[$ns][$elementName][0] = $clazz->newInstance();

		// return it
		return $this->extensions[$ns][$elementName][0];
	}
}

?>